#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "dlist.h"

int dlisthead_init(dlist_t **mylist, int size)
{
	dlist_t *me = NULL;

	me = malloc(sizeof(dlist_t));
	if (NULL == me)
		return -1;
	me->size = size;
	me->node.next = &me->node;
	me->node.prev = &me->node;
	// me->node.data = NULL; // 不用的

	*mylist = me;
	return 0;
}

// 开辟一个新的节点
static struct node_st *__alloc_node(int size, const void *data)
{
	struct node_st *new_node;

	new_node = malloc(sizeof(struct node_st) + size);
	if (NULL == new_node)
		return NULL;
	memcpy(new_node->data, data, size);
	new_node->next = new_node;
	new_node->prev = new_node;

	return new_node;
}

int dlist_empty(const dlist_t *mylist)
{
	return mylist->node.next == &mylist->node && mylist->node.prev == &mylist->node;
}

// 将新的结点插入到两个结点之间
static void __insert_node(struct node_st *p, struct node_st *n, struct node_st *node)
{
	node->prev = p;
	node->next = n;
	p->next = node;
	n->prev = node;
}

int dlist_insert(dlist_t *mylist, const void *data)
{
	// 头插
	struct node_st *n = __alloc_node(mylist->size, data);
	if (NULL == n)
		return -1;

	__insert_node(&mylist->node, mylist->node.next, n);

	return 0;
}

int dlist_insert_tail(dlist_t *mylist, const void *data)
{
	struct node_st *n = __alloc_node(mylist->size, data);
	if (NULL == n)
		return -1;

	__insert_node(mylist->node.prev, &mylist->node, n);

	return 0;
}

static struct node_st *__find_node(const dlist_t *mylist, const void *key, cmp_t cmp)
{
	struct node_st *cur = NULL;

	// 找到key匹配节点的前驱
	for (cur = mylist->node.next; cur != &mylist->node; cur = cur->next)	{
		if (0 == cmp(cur->data, key))
			return cur;
	}

	return NULL;
}

void *dlist_find(const dlist_t *mylist, const void *key, cmp_t cmp)
{
	struct node_st *cur;

	cur = __find_node(mylist, key, cmp);
	if (NULL == cur)
		return NULL;
	return cur->data;
}

static void __delete(struct node_st **d)
{
	(*d)->prev->next = (*d)->next;	
	(*d)->next->prev = (*d)->prev;
	(*d)->prev = (*d)->next = *d;
	free(*d);
	*d = NULL;
}

int dlist_delete(dlist_t *mylist, const void *key, cmp_t cmp)
{
	struct node_st *del;

	del = __find_node(mylist, key, cmp);
	if (NULL == del)
		return -1;

	__delete(&del);

	return 0;
}

void dlist_traval(const dlist_t *mylist, pri_t pri)
{
	struct node_st *cur = NULL;

	for (cur = mylist->node.next; cur != &mylist->node; cur = cur->next) {
		pri(cur->data);
	}
}

static int __always_cmp(const void *data, const void *key)
{
	return 0;
}

void dlist_destroy(dlist_t **mylist)
{
	while (!dlist_empty(*mylist)) {
		dlist_delete(*mylist, NULL, __always_cmp);
	}
	free(*mylist);
	*mylist = NULL;
}



